package main

import (
	"fmt"
	"github.com/quic-go/quic-go"
	"github.com/quic-go/quic-go/http3"
	"github.com/quic-go/webtransport-go"
	"io"
	"log"
	"net/http"
	"strconv"
	"sync"
	"time"
)

var connMap sync.Map

const (
	certFile = "/Users/edy/Desktop/8128616_barrage.houry.top.pem"

	keyFile = "/Users/edy/Desktop/8128616_barrage.houry.top.key"
)

func main() {
	go receiveData()
	go startMonitor()
	go sendData()
	startServe()

}

func startServe() {
	s := webtransport.Server{
		H3: http3.Server{Addr: ":443"},
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
	}

	http.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
		r.Header.Set("Access-Control-Allow-Origin", "*")
		conn, err := s.Upgrade(w, r)
		if err != nil {
			log.Printf("upgrading failed: %s", err)
			w.WriteHeader(500)
			return
		}

		log.Println("-----建立成功----", conn.Context().Value(quic.ConnectionTracingKey))
		connMap.Store(conn, conn)
	})

	err := s.ListenAndServeTLS(certFile, keyFile)
	if err != nil {
		log.Printf("ListenAndServeTLS failed: %s", err)
	}
}

func receiveData() {
	for {
		connMap.Range(func(key, value any) bool {
			connection := value.(*webtransport.Session)
			stream, err := connection.AcceptStream(connection.Context())
			if err != nil {
				log.Println("开启流通道失败:", err)
				connMap.Delete(key)
			} else {
				all, _ := io.ReadAll(stream)
				fmt.Println("接收到数据=", string(all))
				_ = stream.Close()
			}
			return true
		})
	}

}

func sendData() {
	for {
		time.Sleep(time.Second)
		connMap.Range(func(key, value any) bool {
			connection := value.(*webtransport.Session)
			stream, err := connection.OpenUniStreamSync(connection.Context())
			if err != nil {
				log.Println("开启流通道失败:", err)
				connMap.Delete(key)
			} else {
				_, _ = stream.Write([]byte(strconv.FormatInt(time.Now().UnixMilli(), 10)))
				_ = stream.Close()
			}
			return true
		})
	}

}

func startMonitor() {
	log.Println("开始监控连接信息")
	for {
		time.Sleep(time.Second)
		connMap.Range(func(key, value any) bool {
			connection := value.(*webtransport.Session)
			if connection.Context().Err() != nil {
				connMap.Delete(key)
			}
			return true
		})
	}
}
